package com.plian.system.service.transfer.impl;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.plian.Tools.*;
import com.plian.system.constant.sys.FormTypeConstant;
import com.plian.system.entity.pf.BaseGrantSalary;
import com.plian.system.entity.pf.GrantSalary;
import com.plian.system.entity.sys.Org;
import com.plian.system.model.R;
import com.plian.system.service.bt.baseinfo.BaseInfoService;
import com.plian.system.service.pf.IBaseGrantSalaryService;
import com.plian.system.service.pf.IGrantSalaryService;
import com.plian.system.service.sys.code.IFormCodeService;
import com.plian.system.service.sys.orgzation.IOrgService;
import com.plian.system.service.transfer.IGrantSalaryTransferService;
import com.plian.system.service.transfer.ITransferFlowService;
import com.plian.system.vo.pf.BaseGrantSalaryVO;
import com.plian.system.vo.pf.GrantSalaryVO;
import com.plian.system.wrapper.pf.BaseGrantSalaryWrapper;
import com.plian.system.wrapper.pf.GrantSalaryWrapper;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

import static com.plian.system.constant.baseinfo.ValueSetConstant.SALARY_COUNT_CATEGORY;
import static com.plian.system.constant.sys.FormStatusConstant.*;
import static com.plian.system.constant.sys.FormTypeConstant.PF_BASE_GRANT_SALARY;

@Slf4j
@Service
@AllArgsConstructor
public class GrantSalaryTransferServiceImpl implements IGrantSalaryTransferService {

    private IBaseGrantSalaryService baseGrantSalaryService;

    private IGrantSalaryService grantSalaryService;

    private IOrgService orgService;

    private BaseInfoService baseInfoService;

    private BaseGrantSalaryWrapper baseGrantSalaryWrapper;

    private GrantSalaryWrapper grantSalaryWrapper;

    private IFormCodeService formCodeService;

    private ITransferFlowService transferFlowService;

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public R submitGrantSalaryList(List<BaseGrantSalaryVO> baseGrantSalaryVOS) {
        if (CollectionUtil.isEmpty(baseGrantSalaryVOS)){
            return R.success();
        }
        String tokenOrgId = TokenUtil.getTokenOrgId();
        String tokenUserId = TokenUtil.getTokenUserId();
        List<BaseGrantSalary> baseGrantSalaryList = baseGrantSalaryService.list();
        Map<String, BaseGrantSalary> baseMap = baseGrantSalaryList.stream().collect(Collectors.toMap(base -> base.getFillingUnitId()
                + StringPool.UNDERSCORE + base.getFillingMonth() + StringPool.UNDERSCORE + base.getType(), base -> base));
        List<GrantSalary> grantSalaryList = grantSalaryService.list();
        Map<Long, List<GrantSalary>> salaryMap = grantSalaryList.stream().collect(Collectors.groupingBy(GrantSalary::getBaseGrantSalaryId));

        List<Org> allOrg = orgService.getAllChild(tokenOrgId);
        Map<String, Org> orgNameMap = allOrg.stream().collect(Collectors.toMap(Org::getName, org -> org));

        Map<String, String> codeMap = baseInfoService.getChildMap(SALARY_COUNT_CATEGORY);
        List<String> companyMessages = new ArrayList<>();
        List<String> messages = new ArrayList<>();
        List<String> paramMessages = new ArrayList<>();
        List<String> submitIds = new ArrayList<>();
        List<String> addKey = new ArrayList<>();
        for (BaseGrantSalaryVO baseGrantSalaryVO : baseGrantSalaryVOS){
            if (StringUtil.isBlank(baseGrantSalaryVO.getFillingUnitName()) || !orgNameMap.containsKey(baseGrantSalaryVO.getFillingUnitName())){
                companyMessages.add(baseGrantSalaryVO.getFillingUnitName() + ",fillingMonth="
                        + baseGrantSalaryVO.getFillingMonth() + ",type=" + baseGrantSalaryVO.getType() + " 该数据 单位在系统不存在,");
                continue;
            }
            if (StringUtil.isBlank(baseGrantSalaryVO.getFillingMonth()) || baseGrantSalaryVO.getType() == null
                    || (baseGrantSalaryVO.getType() != 1 && baseGrantSalaryVO.getType() != 2)){
                paramMessages.add(baseGrantSalaryVO.getFillingUnitName() + ",fillingMonth="
                        + baseGrantSalaryVO.getFillingMonth() + ",type=" + baseGrantSalaryVO.getType() +  " 必传参数为空,");
                continue;
            }
            baseGrantSalaryVO.setFillingUnitId(orgNameMap.get(baseGrantSalaryVO.getFillingUnitName()).getId());
            String baseKey = baseGrantSalaryVO.getFillingUnitId() + StringPool.UNDERSCORE
                    + baseGrantSalaryVO.getFillingMonth() + StringPool.UNDERSCORE + baseGrantSalaryVO.getType();
            if (addKey.contains(baseKey)){
                continue;
            }
            addKey.add(baseKey);
            if (baseMap.containsKey(baseKey)){
                BaseGrantSalary baseGrantSalary = baseMap.get(baseKey);
                int status = baseGrantSalary.getStatus();
                if (status != UNREVIEWED && status != REJECT && status != STASH){
                    messages.add(baseGrantSalaryVO.getFillingUnitName() + ",fillingMonth="
                            + baseGrantSalaryVO.getFillingMonth() + ",type=" + baseGrantSalaryVO.getType() + " 该数据审批中或已审核,");
                    continue;
                }
                baseGrantSalaryVO.setId(baseGrantSalary.getId());
            }else {
                baseGrantSalaryVO.setCode(formCodeService.getCode(FormTypeConstant.PF_BASE_GRANT_SALARY));
            }

            //保存主表
            BaseGrantSalary base = baseGrantSalaryWrapper.voToEntity(baseGrantSalaryVO);
            base.setCreateCompanyId(base.getFillingUnitId());
            base.setDataSource(tokenUserId);
            base.setStatus(UNREVIEWED);
            base.setFormType(String.valueOf(PF_BASE_GRANT_SALARY));
            base.setIsDeleted(0);
            baseGrantSalaryService.saveOrUpdate(base);
            submitIds.add(String.valueOf(base.getId()));
            List<GrantSalaryVO> grantSalaryVOS = baseGrantSalaryVO.getGrantSalaryVOS();
            if (baseGrantSalaryVO.getId() != null && salaryMap.containsKey(baseGrantSalaryVO.getId())){
                List<GrantSalary> oldSalaryList = salaryMap.get(baseGrantSalaryVO.getId());
                Map<String, GrantSalary> oldSalaryMap = oldSalaryList
                        .stream().collect(Collectors.toMap(GrantSalary::getCountCategoryId, salary -> salary));
                List<GrantSalaryVO> updateList = new ArrayList<>();
                for (GrantSalaryVO salaryVO : grantSalaryVOS){
                    if (oldSalaryMap.containsKey(salaryVO.getCountCategoryId())){
                        GrantSalary oldSalary = oldSalaryMap.get(salaryVO.getCountCategoryId());
                        salaryVO.setId(oldSalary.getId());
                        salaryVO.setLastYearSalary(oldSalary.getLastYearSalary());
                        salaryVO.setActualPeopleNumber(oldSalary.getActualPeopleNumber());
                        salaryVO.setAverageSalary(oldSalary.getAverageSalary());
                        salaryVO.setBaseGrantSalaryId(base.getId());
                        salaryVO.setLastArtificialCost(oldSalary.getLastArtificialCost());
                        salaryVO.setLastCumulativeGrantAmount(oldSalary.getLastCumulativeGrantAmount());
                        salaryVO.setOnJobLastTotalNumber(oldSalary.getOnJobLastTotalNumber());
                        salaryVO.setCumulativeArtificialCost(oldSalary.getCumulativeArtificialCost());
                        salaryVO.setCumulativeGrantAmount(oldSalary.getCumulativeGrantAmount());
                        salaryVO.setOnJobTotalNumber(oldSalary.getOnJobTotalNumber());
                        updateList.add(salaryVO);
                    }
                }
                grantSalaryService.saveList(grantSalaryWrapper.voToEntity(updateList));
                continue;
            }

            //根据code补全子表
            Set<String> tempCodeList = codeMap.keySet();
            for (GrantSalaryVO salaryVO : grantSalaryVOS){
                salaryVO.setBaseGrantSalaryId(base.getId());
                tempCodeList.remove(salaryVO.getCountCategoryId());
            }
            boolean isUnit = baseGrantSalaryVO.getFillingUnitId().equals(tokenOrgId);
            if (CollectionUtil.isNotEmpty(tempCodeList)){
                for (String code : tempCodeList){
                    GrantSalaryVO init = new GrantSalaryVO();
                    if (!isUnit && "085006".equals(code)){
                        continue;
                    }
                    init.setCountCategoryId(code);
                    init.setBaseGrantSalaryId(base.getId());
                    grantSalaryVOS.add(init);
                }
            }
            int year = Integer.valueOf(baseGrantSalaryVO.getFillingMonth().split(StringPool.DASH)[0]);
            int month = Integer.valueOf(baseGrantSalaryVO.getFillingMonth().split(StringPool.DASH)[1]);
            //上月数据
            if (month > 1){
                String lastMonthStr = (month - 1) >= 10 ? "" + (month - 1) : "0" + (month - 1);
                String lastMonthBaseKey =  baseGrantSalaryVO.getFillingUnitId() + StringPool.UNDERSCORE
                        + year + StringPool.DASH + lastMonthStr + StringPool.UNDERSCORE + baseGrantSalaryVO.getType();
                if (baseMap.containsKey(lastMonthBaseKey)){
                    Long lastBaseId = baseMap.get(lastMonthBaseKey).getId();
                    if (salaryMap.containsKey(lastBaseId)){
                        List<GrantSalary> lastMonthSalaryList = salaryMap.get(lastBaseId);
                        Map<String, GrantSalary> lastMonthSalaryMap = lastMonthSalaryList
                                .stream().collect(Collectors.toMap(GrantSalary::getCountCategoryId, salary -> salary));
                        for (GrantSalaryVO salaryVO : grantSalaryVOS){
                            if (lastMonthSalaryMap.containsKey(salaryVO.getCountCategoryId())){
                                GrantSalary lastMonthSalary = lastMonthSalaryMap.get(salaryVO.getCountCategoryId());
                                salaryVO.setLastYearSalary(lastMonthSalary.getLastYearSalary());
                                salaryVO.setActualPeopleNumber(lastMonthSalary.getActualPeopleNumber());
                                salaryVO.setAverageSalary(lastMonthSalary.getAverageSalary());
                                salaryVO.setLastArtificialCost(lastMonthSalary.getCumulativeArtificialCost());
                                salaryVO.setLastCumulativeGrantAmount(lastMonthSalary.getCumulativeGrantAmount());
                                salaryVO.setOnJobLastTotalNumber(lastMonthSalary.getOnJobTotalNumber());
                                salaryVO.setCumulativeArtificialCost(BigDecimalUtil.add(lastMonthSalary.getCumulativeArtificialCost(), salaryVO.getArtificialCost()));
                                salaryVO.setCumulativeGrantAmount(BigDecimalUtil.add(lastMonthSalary.getCumulativeGrantAmount(), salaryVO.getActualGrantAmount()));
                                salaryVO.setOnJobTotalNumber(BigDecimalUtil.add(lastMonthSalary.getOnJobTotalNumber(), salaryVO.getOnJobNumber()));
                            }
                        }
                        grantSalaryService.saveList(grantSalaryWrapper.voToEntity(grantSalaryVOS));
                        continue;
                    }
                }
            }

            // 获取去年年末数据
            String lastBaseKey = baseGrantSalaryVO.getFillingUnitId() + StringPool.UNDERSCORE
                    + year + StringPool.DASH + 12 + StringPool.UNDERSCORE + baseGrantSalaryVO.getType();
            if (baseMap.containsKey(lastBaseKey)){
                Long lastBaseId = baseMap.get(lastBaseKey).getId();
                if (salaryMap.containsKey(lastBaseId)){
                    List<GrantSalary> lastYearSalaryList = salaryMap.get(lastBaseId);
                    Map<String, GrantSalary> lastYearSalaryMap = lastYearSalaryList
                            .stream().collect(Collectors.toMap(GrantSalary::getCountCategoryId, salary -> salary));
                    for (GrantSalaryVO salaryVO : grantSalaryVOS){
                        if (lastYearSalaryMap.containsKey(salaryVO.getCountCategoryId())){
                            GrantSalary lastYearSalary = lastYearSalaryMap.get(salaryVO.getCountCategoryId());
                            salaryVO.setLastYearSalary(lastYearSalary.getCumulativeGrantAmount());
                            salaryVO.setActualPeopleNumber(BigDecimalUtil.divide(lastYearSalary.getOnJobTotalNumber(), new BigDecimal("12"), 2, BigDecimal.ROUND_HALF_UP));
                            salaryVO.setAverageSalary(BigDecimalUtil.divide(salaryVO.getLastYearSalary(), salaryVO.getActualPeopleNumber(), 4, BigDecimal.ROUND_HALF_UP));
                        }
                    }
                }
            }
            grantSalaryService.saveList(grantSalaryWrapper.voToEntity(grantSalaryVOS));
        }

//        if (CollectionUtil.isNotEmpty(submitIds)){
//            transferFlowService.submit(submitIds, FormTypeConstant.PF_BASE_GRANT_SALARY);
//        }
        String resultsMessage = "";
        if (CollectionUtil.isNotEmpty(paramMessages)){
            resultsMessage += paramMessages.stream().collect(Collectors.joining(StringPool.COMMA)) + "必传参数为空，";
        }
        if (CollectionUtil.isNotEmpty(companyMessages)){
            resultsMessage += companyMessages.stream().collect(Collectors.joining(StringPool.COMMA)) + "单位不存在";
        }
        if (CollectionUtil.isNotEmpty(messages)){
            resultsMessage += messages.stream().collect(Collectors.joining(StringPool.COMMA)) + "该数据已上报;";
        }
        return R.data(resultsMessage);
    }

    @Override
    public List<BaseGrantSalaryVO> listByTopOrgId(String topOrgId) {
        List<String> allChildIds = orgService.getAllChildIds(topOrgId);
        if (CollectionUtil.isEmpty(allChildIds)){
            return null;
        }
        List<BaseGrantSalary> baseGrantSalaries = baseGrantSalaryService
                .list(Wrappers.<BaseGrantSalary>lambdaQuery()
                        .in(BaseGrantSalary::getFillingUnitId, allChildIds)
                        .eq(BaseGrantSalary::getStatus, FINISH));
        if (CollectionUtil.isEmpty(baseGrantSalaries)){
            return null;
        }
        Map<Long, List<GrantSalaryVO>> grantSalaryMap = grantSalaryWrapper.entityToVO(grantSalaryService.list(Wrappers.<GrantSalary>lambdaQuery()
                        .in(GrantSalary::getBaseGrantSalaryId, baseGrantSalaries.stream().map(BaseGrantSalary::getId).collect(Collectors.toList()))))
                .stream().collect(Collectors.groupingBy(GrantSalaryVO::getBaseGrantSalaryId));
        List<BaseGrantSalaryVO> baseGrantSalaryVOS = baseGrantSalaryWrapper.entityToVO(baseGrantSalaries);
        for (BaseGrantSalaryVO baseGrantSalaryVO : baseGrantSalaryVOS){
            if (grantSalaryMap.containsKey(baseGrantSalaryVO.getId())){
                baseGrantSalaryVO.setGrantSalaryVOS(grantSalaryMap.get(baseGrantSalaryVO.getId()));
            }
        }
        return baseGrantSalaryVOS;
    }

}
